//
//  CLBlockRealize.c
//  Charles
//
//  Created by Leo on 2017/5/18.
//  Copyright © 2017年 charles. All rights reserved.
//

/**
 int simpleblk() {
    void (^block)(void) = ^(){
        printf("this is charles's block!!");
    };
    block();
    return 1;
 }
 该函数内的block 是如何实现的
*/

#include "CLBlockRealize.h"

#pragma mark - 最简单的block的实现

struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};

struct __simpleblk_block_impl_0 {
    struct __block_impl impl;
    struct __simpleblk_block_desc_0 *Desc;
    __simpleblk_block_impl_0(void *fp,struct __simpleblk_block_desc_0 *desc,int flags = 0){
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

static void __simpleblk_block_func_0(struct __simpleblk_block_impl_0 *__cself) {
    printf("this is charles's simple block!!");
}

static struct __simpleblk_block_desc_0 {
    size_t reserved;
    size_t Block_size;
} __simpleblk_block_desc_0_DATA = {0,sizeof(struct __simpleblk_block_impl_0)};

int simpleblk(){
    
    //声明一个结构体变量
    __simpleblk_block_impl_0 __simpleblk_impl0 = __simpleblk_block_impl_0((void *)__simpleblk_block_func_0,&__simpleblk_block_desc_0_DATA);
    
    //声明一个函数指针变量block，并且将上面的结构体变量的地址付给block指针
    void(*block)(void) = (void(*)())&__simpleblk_impl0;
    
    /*
     下面这句代码 实际上调用的是 __simpleblk_block_func_0（）函数
     是用的函数指针调用函数
     */
    ((void (*)(struct __block_impl *))((struct __block_impl *)block)->FuncPtr)((struct __block_impl *)block);
    
    return 1;
}

#pragma mark - 持有变量的block的实现

struct __variableblk_block_impl_0 {
    struct __block_impl impl;
    struct __variableblk_block_desc_0 *Desc;
    int charles;
    __variableblk_block_impl_0(void *fp,struct __variableblk_block_desc_0 *desc,int _charles, int flags = 0):charles(_charles){
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

struct __variableblk_block_desc_0 {
    size_t reserved;
    size_t Block_size;
} __variableblk_block_desc_0_DATA = {0,sizeof(__variableblk_block_impl_0)};

static void __variableblk_block_func_0(struct __variableblk_block_impl_0 *__cself) {
    int charles = __cself->charles;//这里的charles 是从 variableblk()里面拷贝了一份出来
    printf("this is charles's variable block!! varible is %d",charles);
}

int variableblk() {
    //转换前的代码
    /*
    int charles = 6;
    void (^block)(void) = ^(){
        printf("this is charles's variable block!! varible is %d",charles);
    };
    charles++;
    block();
    */
    //转换后的代码
    
    int charles = 6;
    
    //声明一个结构体变量
    __variableblk_block_impl_0 __variableblk_impl0 = __variableblk_block_impl_0((void *)__variableblk_block_func_0, &__variableblk_block_desc_0_DATA, charles);
    
    //声明一个函数指针并指向 __variableblk_impl0 的地址
    void(*block)(void) = (void(*)())&__variableblk_impl0;
    
    //函数指针调用函数__variableblk_block_func_0
    
    ((void(*)(struct __block_impl *))((struct __block_impl *)block)->FuncPtr)((__block_impl *)block);
    
    return 1;
}

#pragma mark - 可以修改持有变量的block

struct __Block_byref_charles_0 {
    void *__isa;
    __Block_byref_charles_0 *__forwarding;
    int _flags;
    int __size;
    int charles;
};

struct __modifyvariableblk_block_impl_0 {
    struct __block_impl impl;
    struct __modifyvariableblk_block_desc_0 *Desc;
    __Block_byref_charles_0 *charles;
    __modifyvariableblk_block_impl_0(void *fp,struct __modifyvariableblk_block_desc_0 *desc,__Block_byref_charles_0 *_charles,int flags=0):charles(_charles->__forwarding) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

static void __modifyvariableblk_block_func_0(struct __modifyvariableblk_block_impl_0 *__cself){
    __Block_byref_charles_0 *charles = __cself->charles;
    (charles->__forwarding->charles)++;
    printf("this is charles's modify variable block!! varible is %d\n",charles->__forwarding->charles);
}

static void __modifyvariableblk_block_copy_0(struct __modifyvariableblk_block_impl_0 *dst,struct __modifyvariableblk_block_impl_0 *src){
    _Block_object_assign((void *)dst->charles, (void *)src->charles, 8/*BLOCK_FIELD_IS_BYREF*/);
}

static void __modifyvariableblk_block_dispose_0(struct __modifyvariableblk_block_impl_0 *src) {
    _Block_object_dispose((void *)src->charles, 8);
}

struct __modifyvariableblk_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void(*copy)(struct __modifyvariableblk_block_impl_0 *,struct __modifyvariableblk_block_impl_0 *);
    void(*dispose)(struct __modifyvariableblk_block_impl_0 *);
}__modifyvariableblk_block_desc_0_DATA = {0,sizeof(struct __modifyvariableblk_block_impl_0),__modifyvariableblk_block_copy_0,__modifyvariableblk_block_dispose_0};


int modifyvariableblk() {
    //转换前的代码
    /*
    __block int charles = 6;
    void (^block)(void) = ^(){
        charles++;
        printf("this is charles's modify variable block!! varible is %d\n",charles);
    };
    block();
    */
    
    //转换后的代码
    
    //声明一个可以修改的int 变量charles
    __attribute__((__blocks__(byref))) __Block_byref_charles_0 charles = {(void*)0,(__Block_byref_charles_0 *)&charles, 0, sizeof(__Block_byref_charles_0), 6};

    //声明一个结构体变量
    __modifyvariableblk_block_impl_0 modify_block_impl = __modifyvariableblk_block_impl_0((void *)__modifyvariableblk_block_func_0, &__modifyvariableblk_block_desc_0_DATA, (__Block_byref_charles_0*)&charles,570425344);
    
    //声明一个结构体指针 并指向modify_block_impl结构体变量
    void (*block)(void) = (void(*)())&modify_block_impl;
    
    //函数指针调用函数 __modifyvariableblk_block_func_0
    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    
    return 1;
}

